/*!
 * jQuery Input Ip Address Control : v0.1beta (2010/11/09 16:15:43)
 * Copyright (c) 2010 jquery-input-ip-address-control@googlecode.com
 * Licensed under the MIT license and GPL licenses.
 *
 */
(function($){
    String.prototype.isIpv4 = function() {
        rgx = /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/ ;
        return rgx.test(this.toString());
    };
    String.prototype.isIpv6 = function() {
        rgx = /\b([A-F0-9]{1,4}:){7}([A-F0-9]{1,4})\b/i ;
        return rgx.test(this.toString());
    };
    $.fn.extend({
        //Helper Function for Caret positioning
        caret: function(begin, end) {
            if (this.length == 0) return;
            if (typeof begin == 'number') {
                end = (typeof end == 'number') ? end : begin;
                return this.each(function() {
                    if (this.setSelectionRange) {
                        this.focus();
                        this.setSelectionRange(begin, end);
                    } else if (this.createTextRange) {
                        var range = this.createTextRange();
                        range.collapse(true);
                        range.moveEnd('character', end);
                        range.moveStart('character', begin);
                        range.select();
                    }
                });
            } else {
                if (this[0].setSelectionRange) {
                    begin = this[0].selectionStart;
                    end = this[0].selectionEnd;
                } else if (document.selection && document.selection.createRange) {
                    var range = document.selection.createRange();
                    begin = 0 - range.duplicate().moveStart('character', -100000);
                    end = begin + range.text.length;
                }
                return {
                    begin: begin,
                    end: end
                };
            }
        },
        ipAddress: function(s) {
            s = $.extend({
                v:4
            }, s);
            if(s.v == 4) {
                s.rgxcase = new RegExp('[0-9]','g');
                s.label = '___.___.___.___';
            }
            if(s.v == 6) {
                s.rgxcase = new RegExp('[A-F0-9]','gi');
                s.label = '____:____:____:____:____:____:____:____';
            }
            s.place = s.label.split('').pop();
            s.separator = s.label.replace(new RegExp(s.place,'g'),'').split('').pop();
            s.partplace = s.label.split(s.separator).pop();
            //end settings and init
            return $(this).each(function(){
                var ctx = {
                    cursor:null,
                    buffer:null,
                    ip:null,
                    input:null
                };
                ctx.input = $(this);
                if( ctx.input.val() =='' || !isIp(ctx.input.val()))
                    ctx.input.val( s.label );
                ctx.input.attr('maxlength',(s.v==4? 15 : 39)).attr('size',(s.v==4? 15 : 39));

                function isIp(ip) {
                    return eval("ip.isIpv"+s.v+"()");
                };
                function loadCtx() {
                    ctx.cursor = ctx.input.caret();
                    ctx.ip = isIp(unmask(ctx.input.val())) ? unmask(ctx.input.val()) : ctx.ip ;
                    ctx.buffer = ctx.input.val().split('');
                };
                function mask(ip) {
                    var part = ip.split(s.separator);
                    for(var j=0; j<part.length;j++) {
                        while( (s.partplace.length - part[j].length) > 0)
                            part[j] += s.place;
                    }
                    return part.join(s.separator);
                };
                function unmask(ip) {
                    var rgx = new RegExp(s.partplace,'g');
                    var rgx2 = new RegExp(s.place,'g');
                    return ip.replace(rgx,'0').replace(rgx2,'');
                };
                function entryNoCharacter(e) {
                    switch(e.keyCode) {
                        case 8: //backspace
                            if(ctx.buffer[ctx.cursor.end-1] != s.separator) {
                                ctx.buffer[ctx.cursor.end-1] = s.place;
                                ctx.input.val(ctx.buffer.join("")).val();
                            }
                            ctx.input.caret(ctx.cursor.end-1);
                            return false;
                            break;
                        case 13: //enter
                        case 27: //esc
                            ctx.input.blur();
                            break;
                        case 46: //suppr.
                            if(ctx.buffer[ctx.cursor.end] != s.separator && ctx.cursor.end < s.label.length) {
                                ctx.buffer[ctx.cursor.end] = s.place;
                                ctx.input.val(ctx.buffer.join(""));
                            }
                            if(ctx.cursor.end < s.label.length) ctx.input.caret(ctx.cursor.end+1);
                            return false;
                            break;
                    }
                    return true;
                };

                ctx.input.bind('keydown',function(e){
                    loadCtx();
                    //fix for webkit & IE
                    if($.browser.webkit || $.browser.msie) {
                        return entryNoCharacter(e);
                    }
                }).bind('keypress',function(e) {
                    loadCtx();
                    //alternative keys
                    if (e.ctrlKey || e.altKey || e.metaKey) return true;
                    //typeable characters
                    else if ((e.which >= 32 && e.which <= 125) || e.which > 186) {
                        //valid character
                        if(String.fromCharCode(e.which).match(s.rgxcase)) {
                            ctx.buffer[ctx.cursor.end] = String.fromCharCode(e.which);
                            if(!isIp(unmask(ctx.buffer.join('')))) {
                                //delete part if ip is invalid
                                if((ctx.cursor.end == 0 || ctx.buffer[ctx.cursor.end-1]==s.separator)) {
                                    for(var i=ctx.cursor.end+1 ; i<ctx.cursor.end+s.partplace.length ; i++) {
                                        ctx.buffer[i] = s.place;
                                    }
                                }
                                else return false;
                            }
                            ctx.input.val(ctx.buffer.join('')); //ok write
                            if(ctx.buffer[ctx.cursor.end+1] == s.separator) {
                                //part completed ... next part
                                ctx.input.caret(ctx.cursor.end+2);
                            } else {
                                ctx.input.caret(ctx.cursor.end+1);
                            }
                            return false;
                        } //or separator
                        else if(s.separator.charCodeAt(0) == e.which) {
                            var pos = ctx.input.val().indexOf(s.separator, ctx.cursor.end);
                            if(pos == -1) return false;
                            if(ctx.buffer[ctx.cursor.end-1]==s.separator) return false;
                            ctx.cursor.end = pos;
                            ctx.input.caret(ctx.cursor.end+1);
                            return false;
                        }
                        else return false; // or invalid
                    }
                    //no character
                    return entryNoCharacter(e);

                }).bind('blur', function(){
                    if(ctx.input.val() == s.label) return true;
                    var ip = unmask($.trim(ctx.input.val()));
                    if( isIp(ip) ) ctx.input.val(ip);
                    else ctx.input.val( ctx.ip );

                }).bind('focus', function(){
                    setTimeout(function() {
                        loadCtx();
                        if(ctx.input.val() != s.label)
                            ctx.input.val( mask(ctx.ip) );
                        ctx.input.caret(0);
                    }, 0);

                }).bind('paste', function (e){
                    ctx.input.val('');
                    setTimeout(function() {
                        ctx.input.blur();
                    },0);
                });
            });//return each
        }//ipAddress()
    });//$.fn.extends
})(jQuery);

